﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VPLink2014.Data.MesApplis
{
    public static class VPLinkLogExtention
    {
        /// <summary>
        /// Get all directions in table Directions
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static IEnumerable<Direction> AllDirections(this VPLinkLogEntities input)
        {
            return (from dir in input.Directions select dir);
        }


        /// <summary>
        /// Get all departements in table Departements
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static IEnumerable<Departement> AllDepartements(this VPLinkLogEntities input)
        {
            return (from dept in input.Departements select dept);
        }

        /// <summary>
        /// Get all services in table Services
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static IEnumerable<Service> AllServices(this VPLinkLogEntities input)
        {
            return (from sce in input.Services select sce);
        }

        /// <summary>
        /// Get all users in table Users
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static IEnumerable<User> AllUsers(this VPLinkLogEntities input)
        {
            return (from user in input.Users select user);
        }

        /// <summary>
        /// Get all actif users (attribut "actif" == 1) in table Users
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static IEnumerable<User> AllActifUsers(this VPLinkLogEntities input)
        {
            return (from user in input.Users where user.Actif == true select user);
        }

        /// <summary>
        /// Get all actif users (attribut "actif" == 1) in table Users
        /// </summary>
        /// <param name="input"></param>
        /// <param name="orderByTeam">
        /// true : order desc
        /// false : order asc
        /// </param>
        /// <returns></returns>
        public static IEnumerable<User> AllActifUsers(this VPLinkLogEntities input, bool orderByTeam)
        {
            if (orderByTeam)
            {
                return (from user in input.Users
                        where user.Actif == true
                        orderby user.Direction, user.Departement, user.Service, user.Nom
                        select user);
            }
            else
            {
                return (from user  in input.Users
                        where user.Actif == true
                        orderby user.Direction ascending, user.Departement ascending, user.Service ascending
                        select user);
            }
        }

        /// <summary>
        /// Get all interne (email != "prestataire") and actif ("actif" == 1) users from table Users
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static IEnumerable<User> AllInterneActifUsers(this VPLinkLogEntities input)
        {
            foreach (var user in AllActifUsers(input, true))
            {
                if (!user.Email.Contains("prestataire"))
                {
                    yield return user;
                }
            }
        }


        public static IEnumerable<User> AllInterneActifUsersFromService(this VPLinkLogEntities input,
            string serviceName
            , string departementName
            , string directionName)
        {
            return (from user in input.Users
                    where user.Actif == true
                    where !user.Email.Contains("prestataire")
                    where serviceName.Equals(user.Service, StringComparison.CurrentCultureIgnoreCase) == true
                    where departementName.Equals(user.Departement, StringComparison.CurrentCultureIgnoreCase) == true
                    where directionName.Equals(user.Direction, StringComparison.CurrentCultureIgnoreCase) == true
                    orderby user.Direction, user.Departement, user.Service, user.Nom
                    select user);
        }

        public static IEnumerable<User> AllInterneActifUsersFromDepartement(this VPLinkLogEntities input
            , string departementName
            , string directionName)
        {
            return (from user in input.Users
                    where user.Actif == true
                    where !user.Email.Contains("prestataire")
                    where departementName.Equals(user.Departement, StringComparison.CurrentCultureIgnoreCase) == true
                    where directionName.Equals(user.Direction, StringComparison.CurrentCultureIgnoreCase) == true
                    orderby user.Direction, user.Departement, user.Service, user.Nom
                    select user);
        }

        public static IEnumerable<User> AllInterneActifUsersFromDirection(this VPLinkLogEntities input, string directionName)
        {
            return (from user in input.Users
                    where user.Actif == true
                    where !user.Email.Contains("prestataire")
                    where directionName.Equals(user.Direction, StringComparison.CurrentCultureIgnoreCase) == true
                    orderby user.Direction, user.Departement, user.Service, user.Nom
                    select user);
        }

        #region Get Direction, Departement, Service from tables Directions, Departements, Services

        private static bool DoesDeptSceBelongToDirection(Direction dir
            , string departementName
            , string serviceName)
        {
            return dir.Departements.Any(x => departementName.Equals(x.nom, StringComparison.CurrentCultureIgnoreCase)
                && DoesServiceBelongToDepartement(x, serviceName));
        }
        private static bool DoesDeptBelongToDirection(Direction dir, string departementName)
        {
            return dir.Departements.Any(x => departementName.Equals(x.nom, StringComparison.CurrentCultureIgnoreCase));
        }
        private static bool DoesServiceBelongToDepartement(Departement dept, string serviceName)
        {
            return dept.Services.Any(x => serviceName.Equals(x.nom, StringComparison.CurrentCultureIgnoreCase));
        }

        public static List<string> DepartementNameByService(this VPLinkLogEntities input, string serviceName)
        {
            List<string> departements = new List<string>();
            var dept = input.Departements.ToList<Departement>()
                .Where(departement => DoesServiceBelongToDepartement(departement, serviceName))
                .Select(x => x.nom).Distinct();
            return dept.ToList<string>() ?? departements;
        }
        public static List<string> DirectionNameByDepartement(this VPLinkLogEntities input
            , string departementName)
        {
            List<string> directions = new List<string>();
            var dir = input.Directions.ToList<Direction>()
                .Where(direction => DoesDeptBelongToDirection(direction, departementName))
                .Select(x => x.nom);
            if (dir != null)
            {
                directions = dir.ToList<string>();
            }
            return directions;
        }

        public static List<string> DirectionNameByDepartementAndService(this VPLinkLogEntities input
            , string departementName
            , string serviceName)
        {
            List<string> directions = new List<string>();
            var dir = input.Directions.ToList<Direction>()
                .Where(direction => DoesDeptSceBelongToDirection(direction, departementName, serviceName))
                .Select(x => x.nom);
            if (dir != null)
            {
                directions = dir.ToList<string>();
            }
            return directions;
        }
        #endregion

        /// <summary>
        /// Get user by loginname from table Users
        /// </summary>
        /// <param name="input"></param>
        /// <param name="loginName"></param>
        /// <returns></returns>
        public static User GetUserByLoginName(this VPLinkLogEntities input, string loginName)
        {
            return (from user in input.Users
                    where user.LoginUser.Equals(loginName, StringComparison.InvariantCultureIgnoreCase)
                    select user).FirstOrDefault();
        }

        public static IEnumerable<Application> GetDirectionApplications(this VPLinkLogEntities input, string directionName)
        {
            return (from appliDirection in input.AppliDirections
                    from applis in input.Applications
                    from direction in input.Directions
                    where direction.nom == directionName
                    where applis.id == appliDirection.appli
                    where direction.id == appliDirection.direction
                    orderby appliDirection.rang
                    select applis);
        }

        public static IEnumerable<Application> GetDepartementApplications(this VPLinkLogEntities input, string departementName)
        {
            return (from appliDept in input.AppliDepts
                    from applis in input.Applications
                    from departement in input.Departements
                    where departement.nom == departementName
                    where applis.id == appliDept.appli
                    where departement.id == appliDept.departement
                    orderby appliDept.rang
                    select applis);
        }

        public static int nbApplicationsByDirection(this VPLinkLogEntities input, string directionName)
        {
            Direction selectedDirection = input.Directions
                .Where(a => a.nom.Equals(directionName, StringComparison.InvariantCultureIgnoreCase))
                    .First<Direction>();
            if (selectedDirection != null)
            {
                if (input.AppliDirections.Where(x => x.direction == selectedDirection.id) != null)
                {
                    return input.AppliDirections.Where(x => x.direction == selectedDirection.id).Count();
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }
        public static int nbApplicationsByDepartement(this VPLinkLogEntities input, string departementName)
        {
            Departement selectedDepartement = input.Departements
                .Where(a => a.nom.Equals(departementName, StringComparison.InvariantCultureIgnoreCase))
                    .First<Departement>();
            if (selectedDepartement != null)
            {
                if (input.AppliDepts.Where(x => x.departement == selectedDepartement.id) != null)
                {
                    return input.AppliDepts.Where(x => x.departement == selectedDepartement.id).Count();
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }

        public static int nbApplicationsByService(this VPLinkLogEntities input, string serviceName)
        {
            Service selectedService = input.Services
                .Where(a => a.nom.Equals(serviceName, StringComparison.InvariantCultureIgnoreCase))
                    .First<Service>();
            if (selectedService != null)
            {
                if (input.AppliServices.Where(x => x.service == selectedService.id) != null)
                {
                    return input.AppliServices.Where(x => x.service == selectedService.id).Count();
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }
        public static IEnumerable<Application> GetServiceApplications(this VPLinkLogEntities input, string serviceName)
        {
            try
            {
                return (from appliService in input.AppliServices
                        from applis in input.Applications
                        from service in input.Services
                        where service.nom == serviceName
                        where applis.id == appliService.appli
                        where service.id == appliService.service
                        orderby appliService.rang
                        select applis);
            }
            catch (Exception ex)
            {
                string exception = string.Format(@"
								service name : {0}
								exception : {1}", serviceName
                                               //,input..ConnectionString
                                                , ex.StackTrace);
                throw new Exception(exception);
            }
        }

        public static IEnumerable<Application> GetUserApplications(this VPLinkLogEntities input, string loginName)
        {
            try
            {
                return (from appliUsers in input.AppliUsers
                        from applis in input.Applications
                        from userAppli in input.Users
                        where userAppli.LoginUser == loginName
                        where applis.id == appliUsers.appli
                        where userAppli.LoginUser == appliUsers.user
                        orderby appliUsers.rang
                        select applis);
            }
            catch (Exception ex)
            {
                string exception = string.Format(@"
								user name : {0}
								exception : {1}"
                    //, input.Connection.ConnectionString
                    , loginName, ex.StackTrace);
                throw new Exception(exception);
            }
        }
        private static IEnumerable<Application> GetSelectedApplicationsForUserTeam(this VPLinkLogEntities input, User user)
        {
            if (!string.IsNullOrEmpty(user.Service))
            {
                return input.GetServiceApplications(user.Service.ToUpper());
            }
            else
            {
                if (!string.IsNullOrEmpty(user.Departement))
                {
                    return input.GetDepartementApplications(user.Departement);
                }
                else
                {
                    return input.GetDirectionApplications(user.Direction);
                }
            }

        }
        public static IEnumerable<Application> GetSelectedApplicationsForUser(this VPLinkLogEntities input, string loginName)
        {
            User user = input.GetUserByLoginName(loginName);
            if (user.AppliUsers != null)
            {
                if (user.AppliUsers.Count > 0)
                {
                    return input.GetUserApplications(loginName);
                }
                else
                {
                    return input.GetSelectedApplicationsForUserTeam(user);
                }
            }
            else
            {
                return input.GetSelectedApplicationsForUserTeam(user);
            }
        }

        private static int nbApplicationsForUserTeam(this VPLinkLogEntities input, string loginName)
        {
            User user = input.GetUserByLoginName(loginName);
            if (!string.IsNullOrEmpty(user.Service))
            {
                return input.nbApplicationsByService(user.Service);
            }
            else
            {
                if (!string.IsNullOrEmpty(user.Departement))
                {
                    return input.nbApplicationsByDepartement(user.Departement);
                }
                else
                {
                    if (!string.IsNullOrEmpty(user.Direction))
                    {
                        return input.nbApplicationsByDirection(user.Direction);
                    }
                    else
                    {
                        return 0;
                    }
                }
            }
        }

        public static int nbApplicationsForUser(this VPLinkLogEntities input, string loginName)
        {
            User user = input.GetUserByLoginName(loginName);
            if (user != null)
            {
                if (user.AppliUsers == null)
                {
                    return input.nbApplicationsForUserTeam(loginName);
                }
                else
                {
                    if (user.AppliUsers.Count > 0)
                    {
                        return user.AppliUsers.Count;
                    }
                    else
                    {
                        return input.nbApplicationsForUserTeam(loginName);
                    }
                }
            }
            else { return 0; }
        }

        private static int CompareTeamUser(User x, User y)
        {
            if (string.Compare(x.Direction, y.Direction) == 0)
            {
                if (string.Compare(x.Departement, y.Departement) == 0)
                {
                    return string.Compare(x.Service, y.Service);
                }
                else
                {
                    return string.Compare(x.Departement, y.Departement);
                }
            }
            else
            {
                return string.Compare(x.Direction, y.Direction);
            }
        }

    }
}
